﻿using System;
using PortalCurriculo.Util.Security;

namespace PortalCurriculo.Util.PasswordComplexity
{

   /// <summary>
   /// Provides information on dataelements used in the password
   /// </summary>
   [Flags]
   public enum PasswordElements
   {
      /// <summary>
      /// None - Password is empty
      /// </summary>
      None = 0,

      /// <summary>
      /// Password contains one or more digit
      /// </summary>
      Digit = 1,

      /// <summary>
      /// Password contains one or more upper case characters
      /// </summary>
      Uppercase = 2,

      /// <summary>
      /// Password contains one or more lower case characters
      /// </summary>
      Lowercase = 4,

      /// <summary>
      /// Password contains one or more of both the upper  & lower case characters
      /// </summary>
      MixedCase = 6,

      /// <summary>
      /// Password contains one or more 'special' characters
      /// </summary>
      SpecialChar = 8
   }

   /// <summary>
   /// Password strength indicator
   /// </summary>
   public enum PasswordStrengthIndex 
   {
      /// <summary>
      /// Password has no strength - considered insecure (0/4)
      /// </summary>
      None = 0,
      /// <summary>
      /// Password is considered weak (1/4)
      /// </summary>
      Weak = 1,
      /// <summary>
      /// Password is medium strength (2/4)
      /// </summary>
      Medium = 2,
      /// <summary>
      /// Password is strong (3/4)
      /// </summary>
      Strong = 3,
      /// <summary>
      /// Password is strongest set (4/4)
      /// </summary>
      MostStrong = 4,
   }

   /// <summary>
   /// Interface into password determination system
   /// </summary>
   public interface IPassword
   {
      /// <summary>
      /// Given a password it attempts to determine its strength
      /// </summary>
      /// <remarks>
      /// Strength is ultimately deceided by the object 
      /// implementing the password processor
      /// </remarks>
      /// <param name="password">The password.</param>
      /// <returns>Strength indicator</returns>
      PasswordStrengthIndex GetPasswordStrength(string password);

      /// <summary>
      /// Returns an approximation to the entropy for the supplied password
      /// </summary>
      /// <remarks>
      /// Note as this is relatively subjective (unless the password is random)
      /// so it rarely will make sense to compare values between different
      /// password strength providers
      /// </remarks>
      /// <param name="password">The password.</param>
      /// <returns>Calculated strength of password in bits</returns>
      int GetPasswordPseudoEntropy(string password);

      /// <summary>
      /// Checks the password meets policy strength against the policy
      /// </summary>
      /// <param name="password">The password.</param>
      /// <param name="policy">The policy.</param>
      /// <returns>True if password meets the policy, false on failure</returns>
      bool CheckPasswordMeetsPolicyRequirements(string password, IPasswordPolicy policy);

      /// <summary>
      /// Checks the password meets policy strength against the policy and verified the user name is not in the password
      /// </summary>
      /// <param name="userName">The username.</param>
      /// <param name="password">The password.</param>
      /// <param name="policy">The policy.</param>
      /// <returns>True if password meets the policy, false on failure</returns>
      bool CheckPasswordMeetsPolicyRequirements(string userName, string password, IPasswordPolicy policy);
   }
}
